package jp.co.systemi.asp.workflow.apply;

import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import jp.co.systemi.asp.workflow.data.Apply;
import jp.co.systemi.asp.workflow.data.Common;
import jp.co.systemi.asp.workflow.data.PaidHoliday;
import jp.co.systemi.asp.workflow.data.PaidHolidayMeta;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.tools.generic.DateTool;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.PropertyModel;
import org.slim3.datastore.Datastore;
import org.slim3.datastore.GlobalTransaction;

import com.google.appengine.api.datastore.Key;

public class PaidHolidayRefPanel extends Panel implements IApplyInfoPanel {
    private static final long serialVersionUID = -3721209881045255586L;
    /**
     * ログ出力 クラス名をあわせること
     */
    private static final Logger log = Logger
            .getLogger(PaidHolidayRefPanel.class.getName());
    public static final String CATEGORY = "有給休暇";
    List<PaidHoliday> holidays = new ArrayList<PaidHoliday>(); // 申請分または承認済みがまだ未消化（日付が過ぎてない）有給休暇一覧
    // PaidHoliday master = new PaidHoliday();
    PaidHoliday master = null;
    Key applyNo;

    /**
     * コンストラクター 画面の生成、イベント処理の定義はすべて、この中で完結する
     */
    public PaidHolidayRefPanel(String id, PageParameters pars) {
        super(id);
        init(pars);
    }

    private void initData(String loginId, Key applyNo) {
        this.applyNo = applyNo;
        // マスタデータ
        PaidHolidayMeta phm = PaidHolidayMeta.get();
        List<PaidHoliday> masters = Datastore.query(phm).filter(
                phm.loginId.equal(loginId),
                phm.status.equal(Common.APPLY_STATUS.MASTER)).asList();
        if (masters.size() == 0) {
            // マスタデータを作成する
            master = new PaidHoliday();
            master.setLoginId(loginId);
            master.setStatus(Common.APPLY_STATUS.MASTER);
            master.setRemainingDays(0.0); // デフォルト０
            Datastore.put(master);
        } else {
            // master.setRemainingDays(masters.get(0).getRemainingDays());
            master = masters.get(0);
        }
        holidays.clear();
        // 申請中、または承認済みがまだ未消化（日付が過ぎてない）有給休暇一覧を取得
        List<PaidHoliday> holidayData = Datastore.query(phm).filter(
                phm.applyId.equal(applyNo)).sort(phm.startDate.asc).asList();
//        if (holidayData.size() == 0) {
//            error(getString("data.error"));
//            return;
//        }
//        holidays.addAll(holidayData);
        //　項番を設定する
        int i = 0;
        for(PaidHoliday holiday : holidayData){
            holiday.setSeq(++i);
            holidays.add(holiday);
        }
    }

    private void init(PageParameters pars) {
        String loginId = pars.getString("loginId");
        Key applyNo = Datastore.createKey(Apply.class, Long.valueOf(pars
                .getString("applyNo")));
        initData(loginId, applyNo);

        // 有給休暇リスト
        final WebMarkupContainer tblHoliday = new WebMarkupContainer(
                "wi_tblPaidHoliday");
        tblHoliday.setOutputMarkupId(true);
        this.add(tblHoliday);
        tblHoliday.add(new ListView<PaidHoliday>("wi_trPaidHoliday", holidays) {
            private static final long serialVersionUID = 4846361379394092695L;

            @Override
            protected void populateItem(ListItem<PaidHoliday> item) {
                final PaidHoliday holiday = item.getModelObject();
                SimpleDateFormat sdf = new SimpleDateFormat(
                        getString("date.format"));
                item.add(new Label("wi_tdSeq", new PropertyModel<Integer>(
                        holiday, "seq")));

                item.add(new Label("wi_tdApplyNo", new PropertyModel<Long>(
                        holiday, "applyId.id")));
                item.add(new Label("wi_tdStartDate", sdf.format(holiday
                        .getStartDate())));
                item.add(new Label("wi_tdEndDate", sdf.format(holiday
                        .getEndDate())));
                item.add(new Label("wi_tdDays", new PropertyModel<Double>(
                        holiday, "days")));
                item.add(new Label("wi_tdMemo", new PropertyModel<String>(
                        holiday, "memo")));
                item.add(new Label("wi_tdStatus", new PropertyModel<String>(
                        holiday, "status")));
            }
        });
        this.add(new Label("wi_remainingDays", new PropertyModel<Double>(
                master, "remainingDays")));

    }

    public Key getApplyNo() {
        return applyNo;
    }

    public void setApproved(GlobalTransaction gtx) {
        Common.APPLY_STATUS status = Common.APPLY_STATUS.APPROVED;
        for (PaidHoliday holiday : holidays) {
            holiday.setStatus(status);
//            Datastore.put(holiday);
            gtx.put(holiday);
        }
    }

    public void setRejected(GlobalTransaction gtx) {
        Common.APPLY_STATUS status = Common.APPLY_STATUS.REJECTED;
        // マスタデータをまだ更新しない、受入てから、更新する
        for (PaidHoliday holiday : holidays) {
            holiday.setStatus(status);
//            Datastore.put(holiday);
            gtx.put(holiday);
        }
    }

    // 元データは別のPersistenceManagerで管理されているため、パラメータのPersistenceManagerを使えない
    public void setEditing(GlobalTransaction gtx) {
        Common.APPLY_STATUS status = Common.APPLY_STATUS.EDITING;
        for (PaidHoliday holiday : holidays) {
            holiday.setStatus(status);
//            Datastore.put(holiday);
            gtx.put(holiday);
            master.setRemainingDays(master.getRemainingDays()
                    + holiday.getDays());
        }
//        Datastore.put(master);
        gtx.put(master);
    }

//    public Main getApplyPage() {
//        return new PaidHolidayApply();
//    }

    public void setCancelled(GlobalTransaction gtx) {
        Common.APPLY_STATUS status = Common.APPLY_STATUS.CANCELED;
        for (PaidHoliday holiday : holidays) {
            holiday.setStatus(status);
//            Datastore.put(holiday);
            gtx.put(holiday);
            master.setRemainingDays(master.getRemainingDays()
                    + holiday.getDays());
        }
//        Datastore.put(master);
        gtx.put(master);
    }

    public void setAccepted(GlobalTransaction gtx) {
        Common.APPLY_STATUS status = Common.APPLY_STATUS.ACCEPTED;
        for (PaidHoliday holiday : holidays) {
            holiday.setStatus(status);
//            Datastore.put(holiday);
            gtx.put(holiday);
            master.setRemainingDays(master.getRemainingDays()
                    + holiday.getDays());
        }
//        Datastore.put(master);
        gtx.put(master);
    }

    public String getContents(){
        /*
         * create a new instance of the engine
         */

        VelocityEngine ve = new VelocityEngine();
        /*
         * configure the engine. In this case, we are using ourselves as a
         * logger (see logging examples..)
         */

        /*
         * initialize the engine
         */
        /* first, we init the runtime engine. */

        Properties p = new Properties();
        p.setProperty("input.encoding", "UTF-8");
        p.setProperty("runtime.log", "velocity.log");
        p.setProperty("resource.loader", "class");
        p.setProperty("class.resource.loader.description",
                "Velocity Classpath Resource Loader");
        p
                .setProperty("class.resource.loader.class",
                        "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");

        try {
            ve.setProperty("runtime.log.logsystem.class",
                    "org.apache.velocity.runtime.log.NullLogChute");

            ve.init(p);
        } catch (Exception e) {
            log.info(e.getLocalizedMessage());
        }
        Template t = null;
        try {
            t = ve.getTemplate(this.getClass().getPackage().getName().replace(".", "/") + "/PaidHolidayContents.vm");
        } catch (ResourceNotFoundException e) {
            log.info(e.getLocalizedMessage());
        } catch (ParseErrorException e) {
            log.info(e.getLocalizedMessage());
        } catch (Exception e) {
            log.info(e.getLocalizedMessage());
        }
        VelocityContext context = new VelocityContext();
        double days = 0;
        for(PaidHoliday holiday : holidays){
            days += holiday.getDays();
        }
        context.put("date", new DateTool());
        context.put("holidays", holidays);
        context.put("totalDays", days);

        StringWriter sw = new StringWriter();
        try {
            t.merge(context, sw);
        } catch (ResourceNotFoundException e) {
            log.info(e.getLocalizedMessage());
        } catch (ParseErrorException e) {
            log.info(e.getLocalizedMessage());
        } catch (MethodInvocationException e) {
            log.info(e.getLocalizedMessage());
        } catch (IOException e) {
            log.info(e.getLocalizedMessage());
        }
        String msgBody = sw.toString();
        log.info("to send mail " + msgBody);
        return msgBody;
    }
}
